package api

import (
	"fmt"
	"vblog/apps/blog"
	"vblog/ioc"
	"vblog/protocol/middlewares"

	"github.com/gin-gonic/gin"
)

// 处理http报文的一个处理器,通常叫做handler
// 由这个handler类来负责实现具体的api接口,具体的接口放在另外文件(blog.go)
type Handler struct {
	svc blog.Service
}

// Handler的构造函数
// 使用ioc 替换掉直接依赖
func NewHandler() *Handler {
	return &Handler{}
}

// 让他从Ioc中获取依赖的对象
func (h *Handler) Init() error {
	// 获取的对象是一个ioc对象
	// 使用类型断言 来把any --> 真正的业务对象
	// 内置逻辑:blog.AppName 名称 --> blog.Service类型
	var ok bool
	h.svc, ok = ioc.GetController(blog.AppName).(blog.Service)
	if ok {
		return nil
	} else {
		return fmt.Errorf("%v is not a blog.Service", ioc.GetController(blog.AppName))
	}
}

func (h *Handler) Name() string {
	return blog.AppName
}

// 将请求和http路由对应.
// r是http的路由器
func (h *Handler) RegistryApi(r gin.IRouter) {
	// 为这个router创建一个单独的子router,不要和全局的router混用
	// 子Router的中间件加载时是有顺序控制的
	// sr := r.Group("/vblog/api/v1/blogs")

	// 查询博客不需要认证,这个要放在加载中间件之前
	r.GET("", h.QueryBlog)
	// 文章详情
	r.GET("/:id", h.DescribeBlog)
	// 业务模块自己决定使用哪些中间件,所有的后面的接口都需要认证
	r.Use(middlewares.Auth)
	// 创建博客请求用post方法, 用户的请求放到body, get请求不携带body的
	// restful风格api,以POST表示资源的创建
	r.POST("", h.CreateBlog)
	r.PUT("/:id", h.UpdateBlog)
	r.DELETE("/:id", h.DeleteBlog)
}

// 通过import _ "vblog/apps/blog/api"
// 怎么控制加载哪些业务单元
func init() {
	ioc.RegistryHttpApi(&Handler{})
}
